/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package pdf;

import com.lowagie.text.Chunk;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
import com.openbrew.openbrewrf.Administration;
import com.openbrew.openbrewrf.Customer;
import com.openbrew.openbrewrf.Employee;
import com.openbrew.openbrewrf.Firkins;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import javax.imageio.ImageIO;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

/**
 *
 * @author dchapman
 */
public class FirkPDFCreator {

    private Administration admin = null;
    private int linespace = 10;

    private final int borderSize = 50;
    private static final String HELVETICA = "helvetica";
    private static final Font TITLE_FONT = new Font(HELVETICA, Font.BOLD, 12);
    private static final Font TEXT_FONT = new Font(HELVETICA, Font.PLAIN, 8);
    private final DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");

    public void createPDF(final EntityManager en, OutputStream outputStream, Firkins firkin, final Administration admin) {
        if (firkin.getFirkCustomerID() != null) {
            try {
                Document document = new Document(PageSize.A4, borderSize, borderSize, borderSize, borderSize);
                //PdfWriter.getInstance(document, outputStream);   
                PdfWriter writer = PdfWriter.getInstance(document, outputStream);
                document.open();
                PdfContentByte canvas = writer.getDirectContent();
                // Create the Graphics2D object.
                Graphics2D g2d = canvas.createGraphics(PageSize.A4.getWidth(), PageSize.A4.getHeight());

                //Create page 1 image
                makeFirkinSOView(en, g2d, firkin, admin);

                g2d.dispose();

                Paragraph paragraph = new Paragraph();
                paragraph.add(new Chunk(""));
                document.add(paragraph);

                document.close();
            } catch (DocumentException ex) {

            }
        }
    }

    public void setView(final Administration admin) {
        this.admin = admin;
    }

    private void makeFirkinSOView(final EntityManager en, final Graphics2D g2d, Firkins firkin, Administration admin) {
        setView(admin);
        g2d.setPaint(Color.BLACK);
        //Draw Graphics to PDF.
        addGraphics(g2d);

        //Draw Header to PDF.
        addHeaderInfo(en, g2d, firkin);

        //Draw Invoice Data to PDF.
        addCustomerInvoiceData(en, g2d, firkin);

        //Draw Footer Data to PDF.
        addFooterData(g2d);
    }

    private void addGraphics(final Graphics2D g2d) {
        // Print Logos (Logo.JPG and BLogo.JPG
        BufferedImage image = null;
        BufferedImage image2 = null;
        if (admin.getHeaderImg() != null) {
            try {
                InputStream in = new ByteArrayInputStream(admin.getHeaderImg());
                BufferedImage hdrbi = ImageIO.read(in);
                image = hdrbi;
            } catch (IOException ex) {

            }
        }
        if (admin.getFooterImg() != null) {
            try {
                InputStream in = new ByteArrayInputStream(admin.getFooterImg());
                BufferedImage hdrbi = ImageIO.read(in);
                image2 = hdrbi;
            } catch (IOException ex) {

            }
        }
        // Render the image on the sheet
        g2d.drawImage(image, borderSize, borderSize, 66, 100, null);
        final double imgy = (PageSize.A4.getHeight() - 66 - borderSize);
        final double imgx = (PageSize.A4.getWidth() - 66 - borderSize);
        // Render second image on sheet.
        g2d.drawImage(image2, (int) imgx, (int) imgy, 66, 66, null);
    }

    private String getDisplayID(final int id) {
        final String mask = "firk000000";
        final String ds = Integer.toString(id);
        return mask.substring(0, mask.length() - ds.length()) + ds;
    }

    private Customer getCustomerFromID(final EntityManager en, final long custID) {
        TypedQuery<Customer> query = en.createQuery(
                "SELECT c FROM Customer c WHERE c.cId = ?1", Customer.class);
        query.setParameter(1, custID);
        return query.getSingleResult();
    }

    private void addHeaderInfo(final EntityManager en, final Graphics2D g2d, final Firkins firkin) {
        // ---Section 1 (Header)
        // Print the header
        final String titleText = admin.getBreweryName();
        g2d.setFont(TITLE_FONT);

        // Comput the right alignment on the page.
        FontMetrics fontMetrics = g2d.getFontMetrics();
        final double titleX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(titleText));
        final double titleY = 14 + borderSize;
        g2d.drawString(titleText, (int) titleX, (int) titleY);

        // Print the address.
        final String addressText0 = admin.getBreweryStreetAddress() + " "
                + admin.getBreweryCity() + ", " + admin.getBreweryState() + " "
                + admin.getBreweryZipCode();
        final String addressText1 = admin.getBreweryPhoneNumber();
        final String addressText2 = admin.getBreweryEmail();
        final int addressY = 14 + borderSize;
        g2d.setFont(TEXT_FONT);

        // Compute the right alignment for the address info.
        fontMetrics = g2d.getFontMetrics();
        double addressX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(addressText0));
        g2d.drawString(addressText0, (int) addressX, (addressY + (linespace * 1)));
        addressX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(addressText1));
        g2d.drawString(addressText1, (int) addressX, (addressY + (linespace * 2)));
        addressX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(addressText2));
        g2d.drawString(addressText2, (int) addressX, (addressY + (linespace * 3)));

        // Get Sales Order information.
        Customer customer = getCustomerFromID(en, firkin.getFirkCustomerID().getcId());

        // Print Invoice Data:
        final String invoiceNumberString = "INVOICE NUMBER: " + getDisplayID(firkin.getFirkID());
        final String invoiceDateString = "INVOICE DATE: " + dateFormat.format(firkin.getFirkSalesDate());
        final String invoiceDueString = "DUE DATE: " + dateFormat.format(firkin.getDueDate(customer.getCTerms()));
        g2d.setFont(TEXT_FONT);

        // Compute the right alignment for the invoice info.
        fontMetrics = g2d.getFontMetrics();
        double textX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(invoiceNumberString));
        final int iY = (addressY + (linespace * 5));
        g2d.drawString(invoiceNumberString, (int) textX, (iY + (linespace * 1)));
        textX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(invoiceDateString));
        g2d.drawString(invoiceDateString, (int) textX, (iY + (linespace * 2)));
        textX = (PageSize.A4.getWidth() - borderSize) - (fontMetrics.stringWidth(invoiceDueString));
        g2d.drawString(invoiceDueString, (int) textX, (iY + (linespace * 3)));
    }

    private void addFooterData(final Graphics2D g2d) {
        // -- Section 3 (Footer)
        Employee billingEmp = admin.getBillingEmp();
        Employee salesEmp = admin.getSalesEmp();
        // Print Contact Info.
        final String gContact = "Contact Info:";
        final String gBilling = "Billing: " + billingEmp.getEmpFirstName() + " "
                + billingEmp.getEmpLastName() + " - " + billingEmp.getEmpPhone();
        final String gBillingAddr = billingEmp.getEmpEmail();
        final String gSales = "Sales: " + salesEmp.getEmpFirstName() + " "
                + salesEmp.getEmpLastName() + " - " + salesEmp.getEmpPhone();
        final String gSalesAddr = salesEmp.getEmpEmail();

        // Compute and display contact info.
        double textX = 0 + borderSize;
        final double textY = (PageSize.A4.getHeight() - 66 - borderSize);
        linespace = 10;

        g2d.drawString(gContact, (int) textX, (int) textY);
        g2d.drawString(gBilling, (int) textX, ((int) textY + (linespace * 2)));
        g2d.drawString(gBillingAddr, (int) textX, ((int) textY + (linespace * 3)));
        g2d.drawString(gSales, (int) textX, ((int) textY + (linespace * 5)));
        g2d.drawString(gSalesAddr, (int) textX, ((int) textY + (linespace * 6)));
    }

    private void addCustomerInvoiceData(final EntityManager en, final Graphics2D g2d, final Firkins firkin) {
        FontMetrics fontMetrics = g2d.getFontMetrics();
        Customer customer = getCustomerFromID(en, firkin.getFirkCustomerID().getcId());
        // -- Section 2 (Customer data and invoice)
        // Print Customer Data:
        final String custTo = "TO:";
        final String custName = customer.getCName();
        final String custAddr = customer.getCAddr();
        final String custCSZ = customer.getCCity() + ", " + customer.getCState() + " " + customer.getCZip();
        final String custPhone = customer.getCPhone();

        // Calculate Customer Position.
        final int cY = 180 + borderSize;
        double textX = (fontMetrics.stringWidth(custTo) + 6) + borderSize;
        g2d.drawString(custTo, borderSize, (cY + (linespace * 1)));
        g2d.drawString(custName, (int) textX, (cY + (linespace * 1)));
        g2d.drawString(custAddr, (int) textX, (cY + (linespace * 2)));
        g2d.drawString(custCSZ, (int) textX, (cY + (linespace * 3)));
        g2d.drawString(custPhone, (int) textX, (cY + (linespace * 4)));

        // -- Section 2 Part B List Invoice.
        final int dateFieldXPosition = 0 + borderSize;
        final int productFieldXPosition = 75 + borderSize;
        final double costFieldXPosition = PageSize.A4.getWidth() - productFieldXPosition;
        int tY = cY + (linespace * 6);

        // Print out headers of file.
        String headerDate = "Date:";
        final String headerProduct = "Product:";
        final String headerCost = "Cost:";

        g2d.drawString(headerDate, dateFieldXPosition, tY);
        g2d.drawString(headerProduct, productFieldXPosition, tY);
        g2d.drawString(headerCost, (int) costFieldXPosition, tY);

        tY += linespace;

        g2d.drawString(dateFormat.format(firkin.getFirkSalesDate()), dateFieldXPosition, tY);
        g2d.drawString(firkin.getFirkDesc(), productFieldXPosition, tY);
        g2d.drawString(Float.toString(firkin.getFirkCost()), (int) costFieldXPosition, tY);

        tY += linespace;

        final String totalCost = Float.toString(firkin.getFirkCost());
        final String ttl = "Total:";

        final double ttlX = PageSize.A4.getWidth() - borderSize - productFieldXPosition - fontMetrics.stringWidth(ttl) - 5;

        g2d.drawString(totalCost, (int) costFieldXPosition, tY);
        g2d.drawString(ttl, (int) ttlX, tY);
    }
}
